package com.yth.utils;

import org.apache.commons.collections.CollectionUtils;

import java.util.*;
import java.util.function.Function;

/**
 * @author yutianhong
 * @version 1.0
 * @since 2024/12/10 14:01
 */
public class ValidateUtils {
    // Java中的关键字和保留字集合
    private static final Set<String> keywords;

    static {
        String[] kws = {
                "abstract", "continue", "for", "new", "switch",
                "assert", "default", "goto", "package", "synchronized",
                "boolean", "do", "if", "private", "this",
                "break", "double", "implements", "protected", "throw",
                "byte", "else", "import", "public", "throws",
                "case", "enum", "instanceof", "return", "transient",
                "catch", "extends", "int", "short", "try",
                "char", "final", "interface", "static", "void",
                "class", "finally", "long", "strictfp", "volatile",
                "const", "float", "native", "super", "while",
                "true", "false", "null"
        };
        Set<String> set = new HashSet<>(Arrays.asList(kws));
        keywords = Collections.unmodifiableSet(set);
    }

    /**
     * 检测循环依赖
     *
     * @param dependencies
     * @return 导致循环依赖的一个节点
     */
    public static String checkForCycles(Map<String, ? extends Collection<String>> dependencies) {
        Set<String> visiting = new HashSet<>();
        Set<String> visited = new HashSet<>();

        for (String node : dependencies.keySet()) {
            if (!visited.contains(node)) {
                if (hasCycle(node, dependencies, visiting, visited)) {
                    return node;
                }
            }
        }
        return null;
    }

    private static boolean hasCycle(String node, Map<String, ? extends Collection<String>> dependencies, Set<String> visiting, Set<String> visited) {
        // If we're already visiting this node, we've found a cycle
        if (visiting.contains(node)) {
            return true;
        }
        // If we've already visited this node, no need to do anything
        if (visited.contains(node)) {
            return false;
        }

        visiting.add(node);

        Collection<String> collection = dependencies.get(node);
        if (collection != null) {
            for (String neighbor : collection) {
                if (hasCycle(neighbor, dependencies, visiting, visited)) {
                    return true;
                }
            }
        }

        visiting.remove(node);
        visited.add(node);
        return false;
    }

    public static <E, V> Set<V> getDuplicates(Collection<E> collection, Function<E, V> function) {
        if (CollectionUtils.isEmpty(collection)) {
            return Collections.emptySet();
        }
        Set<V> duplicates = new HashSet<>();
        Set<V> elements = new HashSet<>();
        for (E e : collection) {
            V v = function.apply(e);
            if (!elements.add(v)) {
                duplicates.add(v);
            }
        }
        return duplicates;
    }

    /**
     * 检查是否是有效的变量名
     */
    public static boolean isValidVariableName(String name) {
        // 检查是否为null或者空字符串
        if (name == null || name.isEmpty()) {
            return false;
        }

        // 检查第一个字符是否是合法的Java标识符起始字符
        if (!Character.isJavaIdentifierStart(name.charAt(0))) {
            return false;
        }

        // 检查其余字符是否为合法的Java标识符字符
        for (int i = 1; i < name.length(); i++) {
            if (!Character.isJavaIdentifierPart(name.charAt(i))) {
                return false;
            }
        }

        return true;
    }

    /**
     * 检查是否是有效的Java变量名（包括关键字检查）
     */
    public static boolean isValidJavaVariableName(String name) {
        // 检查是否为关键字
        return isValidVariableName(name) && !keywords.contains(name);
    }

}
